﻿// <copyright file="NonRootDirectoryContainer.cs" company="Sinclair Community College">
// Copyright 2010 Sinclair Community College
// </copyright>
// <originalAuthor>Patrick S. Seymour (patrick.seymour@gmail.com)</originalAuthor>

namespace SinclairCC.AppV
{
    using System;
    using System.Collections.Generic;
    using System.IO;

    /// <summary>
    /// This container represents containers of type PACKAGE_DIRECTORY and RUN_DIRECTORY.
    /// </summary>
    /// <remarks>
    /// A Package Directory Container points to a directory structure which was created by App-V Sequencer and is part of a package.
    /// A Run Directory Container points to a directory structure which has been generated during the package runtime.
    /// </remarks>
    public class NonRootDirectoryContainer : Container
    {
        private StorageBlockInfoTable storageBlockTable;
        private System.Collections.ObjectModel.Collection<_DIRECTORY_STRUCT_PRIMARY> childDirectories;

        public NonRootDirectoryContainer(System.IO.BinaryReader fileReader)
            : base(fileReader)
        {
            this.childDirectories = new System.Collections.ObjectModel.Collection<_DIRECTORY_STRUCT_PRIMARY>();
            this.storageBlockTable = null;
            this.ReadContainer(fileReader);
        }

        /// <summary>
        /// Reads the actual data for this container from the file.
        /// </summary>
        protected void ReadContainer(System.IO.BinaryReader fileReader)
        {
            if ((this.Header.StorageType & DataStorageType.FORMAT_BLOCKMAP) == DataStorageType.FORMAT_BLOCKMAP)
            {
                this.storageBlockTable = new StorageBlockInfoTable(fileReader);
            }
            else if ((this.Header.StorageType & DataStorageType.FORMAT_INLINE) == DataStorageType.FORMAT_INLINE)
            {
                this.ReadDirectoryStructs(fileReader);
            }
        }

        private void ReadDirectoryStructs(BinaryReader reader)
        {
            _DIRECTORY_STRUCT_PRIMARY dirStruct;
            do
            {
                dirStruct = new _DIRECTORY_STRUCT_PRIMARY(reader);
                if (dirStruct.StructureType != 0)
                {
                    this.childDirectories.Add(dirStruct);
                    //Console.WriteLine("{0} {1}", dirStruct.LongName, dirStruct.ShortName.Length > 0 ? string.Format("[{0}]", dirStruct.ShortName) : string.Empty);
                }
            }
            while ((reader.BaseStream.Length > reader.BaseStream.Position) /* && (dirStruct.StructureType != 0) */ );
        }

        public StorageBlockInfoTable StorageBlockTable
        {
            get { return this.storageBlockTable; }
        }

        public System.Collections.ObjectModel.Collection<_DIRECTORY_STRUCT_PRIMARY> ChildDirectories
        {
            get { return this.childDirectories; }
        }


        /*
        public void ProcessOld(uint containerSize, uint storageBlockSize, System.IO.BinaryReader fileReader)
        {

            long position = fileReader.BaseStream.Position;
            foreach (StorageBlockInfo sbi in this.storageBlockTable)
            {
                long offset = sbi.GetOffset(containerSize, storageBlockSize);
                if (offset != -1)
                {
                    // Seek to the container's offset.
                    fileReader.BaseStream.Seek(offset, SeekOrigin.Begin);

                    byte[] buffer = new byte[storageBlockSize];
                    int bytesRead = fileReader.Read(buffer, 0, buffer.Length);

                    MemoryStream byteStream = new MemoryStream(buffer, false);
                    System.IO.BinaryReader bufferReader = new System.IO.BinaryReader(byteStream);

                    this.ReadDirectoryStructs(bufferReader, ConsoleColor.Magenta);

                    bufferReader.Close();
                    byteStream.Close();
                    byteStream.Dispose();
                }
            }
            fileReader.BaseStream.Seek(position, SeekOrigin.Begin);
        }
        */
        
        public void Process(uint containerSize, uint storageBlockSize, System.IO.BinaryReader fileReader)
        {
            long position = fileReader.BaseStream.Position;
            foreach (StorageBlockInfo sbi in this.storageBlockTable)
            {
                long offset = sbi.GetOffset(containerSize, storageBlockSize);
                if (offset != -1)
                {
                    // Seek to the container's offset.
                    fileReader.BaseStream.Seek(offset, SeekOrigin.Begin);
                    byte[] storageBlockBuffer = new byte[storageBlockSize];
                    int bytesRead = fileReader.Read(storageBlockBuffer, 0, storageBlockBuffer.Length);

                    MemoryStream storageBlockStream = new MemoryStream(storageBlockBuffer, false);
                    System.IO.BinaryReader storageBlockReader = new System.IO.BinaryReader(storageBlockStream);
                        
                    this.ReadDirectoryStructs(storageBlockReader);

                    storageBlockReader.Close();
                    storageBlockStream.Close();
                    storageBlockStream.Dispose();
                }
            }
            fileReader.BaseStream.Seek(position, SeekOrigin.Begin);
        }
        
    }
}
